﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using UnityEngine;
using UnityEngine.Networking;

public class IPDownloadExtension
{
    public const string DownloadFileNameSuffix = ".ipt";
    public static string DownloadFileSavePathPrefix = Application.dataPath + "/../";

    /// <summary>
    /// 通过URL获取文件名
    /// 先检查最后一部分作为文件名是否合法，否则使用Hash代替
    /// </summary>
    public static string GetNameByUrl(string url)
    {
        if (string.IsNullOrEmpty(url))
        {
            return "";
        }

        string alternativeName = url.Substring(url.LastIndexOf('/') + 1);//备选名称
        bool isLegal = CheckFileNameLegal(alternativeName);

        return isLegal ? alternativeName : alternativeName.GetHashCode().ToString();
    }

    /// <summary>
    /// 检查文件名是否合法
    /// </summary>
    public static bool CheckFileNameLegal(string fileName)
    {
        Regex regex = new Regex(@"^[^\/\:\*\?\""\<\>\|\,]+$");
        Match match = regex.Match(fileName);

        return match.Success;
    }
}

public enum DownloadState
{
    Download,
    Stop,
    Done,
}

public class IPDownloadJob
{
    public UnityWebRequest downloadRequest;
    public DownloadState jobState;
}

public class IPDownloadManager : MonoBehaviour
{
    private static IPDownloadManager _instance;

    public static IPDownloadManager GetInstance()
    {
        if (_instance == null)
        {
            GameObject go = new GameObject("IPDownloadManager");
            _instance = go.AddComponent<IPDownloadManager>();
        }

        return _instance;
    }

    private event Action<string> OnAnyDownloadJobStartEvent = null;//任一任务开始下载
    private event Action<string> OnAnyDownloadJobPauseEvent = null;//任一任务暂停下载
    private event Action<string> OnAnyDownloadJobCompleteEvent = null;//任一任务下载完成

    /// <summary>
    /// URL:下载任务请求
    /// </summary>
    private Dictionary<string, IPDownloadJob> DownloadJobRequestTable = new Dictionary<string, IPDownloadJob>();

    public bool TryGetIPDownloadJob(string url, out IPDownloadJob job)
    {
        if (DownloadJobRequestTable.TryGetValue(url, out job))
        {
            return true;
        }

        return false;
    }

    /// <summary>
    /// 创建下载任务
    /// </summary>
    public void StartDownloadJob(string url, string appointName = "")
    {
        string fileName = !string.IsNullOrEmpty(appointName) ? appointName : IPDownloadExtension.GetNameByUrl(url);
        DownloadFileInfo tempInfo = new DownloadFileInfo(fileName);
        if (File.Exists(tempInfo.FilePath))
        {
            Debug.Log(tempInfo.FileName + "已下载完成，请前往下载目录查看：" + tempInfo.FilePath);
            //todo 询问是否覆盖下载

            return;
        }

        IPDownloadJob downloadJob = null;
        if (TryGetIPDownloadJob(url, out downloadJob))//存在任务
        {
            if (downloadJob.jobState == DownloadState.Download)
            {
                Debug.Log(url + "任务正在下载，请等待");

                return;
            }
        }

        DownloadJobHandler jobHandler = new DownloadJobHandler(url);
        jobHandler.OnReceiveTotalLengthEvent += (length) => { Debug.Log(length); };
        jobHandler.OnReceiveRemainingLengthEvent += (length) => { Debug.Log(length); };
        jobHandler.OnReceiveDataEvent += (progress) => { Debug.Log(url + " " + progress); };
        jobHandler.OnDownloadJobCompleteEvent += (str) =>
                 {
                     DownloadJobRequestTable.Remove(url);
                     Debug.Log(str);
                 };

        UnityWebRequest request = UnityWebRequest.Get(url);
        request.chunkedTransfer = true;
        request.disposeDownloadHandlerOnDispose = true;
        request.SetRequestHeader("Range", "bytes=" + jobHandler.FileDownloadedLength + "-");
        request.downloadHandler = jobHandler;
        request.SendWebRequest();

        downloadJob = new IPDownloadJob();
        downloadJob.jobState = DownloadState.Download;
        downloadJob.downloadRequest = request;

        DownloadJobRequestTable.Add(url, downloadJob);
        Debug.Log(url + "下载任务启动");
    }

    public void StopDownloadJob(string url)
    {
        IPDownloadJob downloadJob = null;
        if (!TryGetIPDownloadJob(url, out downloadJob))
        {
            Debug.Log("下载任务不存在：" + url);

            return;
        }

        DownloadJobHandler job = downloadJob.downloadRequest.downloadHandler as DownloadJobHandler;
        job.DisposeJob();

        downloadJob.jobState = DownloadState.Stop;
        downloadJob.downloadRequest.Abort();
        downloadJob.downloadRequest.Dispose();

        DownloadJobRequestTable.Remove(url);
        Debug.Log(url + "下载任务暂停");
    }

    private void OnApplicationQuit()
    {
        foreach (var kpv in DownloadJobRequestTable)
        {
            var job = kpv.Value.downloadRequest.downloadHandler as DownloadJobHandler;
            job.DisposeJob();
            kpv.Value.downloadRequest.Dispose();
        }

        DownloadJobRequestTable.Clear();
    }
}